.\" $OpenBSD: OBJ_NAME_add.3,v 1.6 2024/01/31 08:02:53 tb Exp $
.\"
.\" Copyright (c) 2021 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 31 2024 $
.Dt OBJ_NAME_ADD 3
.Os
.Sh NAME
.Nm OBJ_NAME_add ,
.Nm OBJ_NAME_remove ,
.Nm OBJ_NAME_get ,
.Nm OBJ_NAME_new_index ,
.Nm OBJ_NAME_init ,
.Nm OBJ_NAME_cleanup
.Nd global associative array
.Sh SYNOPSIS
.In openssl/objects.h
.Ft int
.Fo OBJ_NAME_add
.Fa "const char *name"
.Fa "int type"
.Fa "const char *value"
.Fc
.Ft int
.Fo OBJ_NAME_remove
.Fa "const char *name"
.Fa "int type"
.Fc
.Ft const char *
.Fo OBJ_NAME_get
.Fa "const char *name"
.Fa "int type"
.Fc
.Ft int
.Fo OBJ_NAME_new_index
.Fa "unsigned long (*hash_func)(const char *name)"
.Fa "int (*cmp_func)(const char *name1, const char *name2)"
.Fa "void (*free_func)(const char *name, int type, const char *value)"
.Fc
.Ft int
.Fn OBJ_NAME_init void
.Ft void
.Fn OBJ_NAME_cleanup "int type"
.Bd -literal
typedef struct {
        int	    type;
        int	    alias;
        const char *name;
        const char *data;
} OBJ_NAME;
.Ed
.Sh DESCRIPTION
These functions implement a single, static associative array
with the following properties:
.Bl -bullet
.It
The keys are ordered pairs consisting of a NUL-terminated string
.Pq called the Fa name
and an
.Vt int
number
.Pq called the Fa type .
Two types are predefined and used internally by the library:
.Dv OBJ_NAME_TYPE_MD_METH
and
.Dv OBJ_NAME_TYPE_CIPHER_METH .
Two additional types are predefined but not used internally:
.Dv OBJ_NAME_TYPE_PKEY_METH
and
.Dv OBJ_NAME_TYPE_COMP_METH .
All predefined types are greater than
.Dv OBJ_NAME_TYPE_UNDEF
and smaller than
.Dv OBJ_NAME_TYPE_NUM .
.It
The values are pointers.
Formally, they are of the type
.Vt const char * ,
but in practice, pointers of other types, for example
.Vt EVP_CIPHER *
or
.Vt EVP_MD * ,
are often stored as values
and cast back to the correct type on retrieval.
.It
The array supports type-specific aliases for names.
.El
.Pp
.Fn OBJ_NAME_add
removes the key-value pair or alias with the key
.Pq Fa name , type
in the same way as
.Fn OBJ_NAME_remove
and inserts a key-value pair with the specified
.Fa name ,
.Fa type ,
and
.Fa value .
If the bit
.Dv OBJ_NAME_ALIAS
is set in the
.Fa type
argument, that bit is cleared before using the
.Fa type
and the key
.Pq Fa name , type
becomes an alias for the key
.Pq Fa value , type
instead of setting a value.
It is not checked whether the key
.Pq Fa value , type
already exists.
Consequently, it is possible to define an alias
before setting the associated value.
.Pp
.Fn OBJ_NAME_remove
removes the key-value pair or alias with the key
.Pq Fa name , type
from the array, if it exists.
Otherwise, it has no effect.
If the bit
.Dv OBJ_NAME_ALIAS
is set in the
.Fa type
argument, it is ignored and cleared before using the
.Fa type .
If the
.Fa type
is an application-defined type added with
.Fn OBJ_NAME_new_index
and the
.Fa free_func
associated with the
.Fa type
is not a
.Dv NULL
pointer, it is called with the
.Fa name ,
.Fa type ,
and
.Fa value
of the key-value pair being removed or with the
.Fa name ,
.Fa type ,
and alias target name of the alias being removed.
In typical usage, this function might free the
.Fa name ,
and it might free the
.Fa value
in a type-specific way.
.Pp
.Fn OBJ_NAME_get
looks up the key
.Pq Fa name , type ,
recursively resolving up to ten aliases if needed.
If the bit
.Dv OBJ_NAME_ALIAS
is set in the
.Fa type
argument, it is cleared before using the
.Fa type ,
processing of aliases is disabled, and if
.Pq Fa name , type
is an alias, the target name of the alias is returned instead of a value.
.Pp
.Fn OBJ_NAME_new_index
assigns the smallest unassigned positive integer number
to represent a new, application-defined
.Fa type .
The three function pointers will be used, respectively,
to hash a name for this type, to compare two names for this type,
and to free the contents of a key-value pair holding the given
.Fa name ,
.Fa type ,
and
.Fa value .
If the
.Fa hash_func
argument is a
.Dv NULL
pointer,
.Xr lh_strhash 3
is used instead.
If the
.Fa cmp_func
argument is a
.Dv NULL
pointer,
.Xr strcmp 3
is used instead.
If the
.Fa free_func
argument is a
.Dv NULL
pointer, the
.Fa name
and
.Fa value
pointers contained in the key-value pair are not freed,
only the structure representing the pair itself is.
This default behaviour is also used for the built-in types.
.Pp
.Fn OBJ_NAME_init
initializes the array.
After initialization, the array is empty.
Calling
.Fn OBJ_NAME_init
when the array is already initialized has no effect.
Application programs do not need to call this function because
.Fn OBJ_NAME_add
and
.Fn OBJ_NAME_get
automatically call it whenever needed.
.Pp
.Fn OBJ_NAME_cleanup
removes all key-value pairs and aliases of the given
.Fa type
from the array by calling
.Fn OBJ_NAME_remove
on every such pair and alias.
If the
.Fa type
argument is negative, it removes all key-value pairs and aliases
of any type and also reverses all effects of
.Fn OBJ_NAME_new_index
and
.Fn OBJ_NAME_init ,
in particular resetting the list of types to the predefined types
and releasing all memory reserved by these functions.
.Pp
The
.Vt OBJ_NAME
structure represents one key-value pair or one alias with the key
.Pq Fa name , type .
If the
.Fa alias
field is 0, the
.Fa data
field contains the value; otherwise, it contains the alias target name.
.Sh RETURN VALUES
.Fn OBJ_NAME_add
and
.Fn OBJ_NAME_init
return 1 on success or 0 if memory allocation fails.
.Pp
.Fn OBJ_NAME_remove
returns 1 if one key-value pair or alias was removed or 0 otherwise.
.Pp
.Fn OBJ_NAME_get
returns the
.Fa value
associated with the key
.Pq Fa name , type
or
.Dv NULL
if
.Fa name
is
.Dv NULL ,
if the array does not contain a value for this key,
or if more than ten aliases are encountered before finding a value.
.Pp
.Fn OBJ_NAME_new_index
returns a positive integer greater than or equal to
.Dv OBJ_NAME_TYPE_NUM
representing the new type or 0 if memory allocation fails.
.Sh SEE ALSO
.Xr EVP_cleanup 3 ,
.Xr EVP_get_cipherbyname 3 ,
.Xr EVP_get_digestbyname 3 ,
.Xr lh_new 3 ,
.Xr OBJ_create 3 ,
.Xr OBJ_nid2obj 3
.Sh BUGS
Calling
.Fn OBJ_NAME_get
with the bit
.Dv OBJ_NAME_ALIAS
is not very useful because there is no way to tell
whether the returned pointer points to a value or to a name,
short of calling the function again without setting the bit
and comparing the two returned pointers.
.Pp
The
.Fa free_func
has no way to tell whether its
.Fa value
argument is indeed of the given
.Fa type
or whether it is merely the target name of an alias.
Consequently, to use values of a type
that requires more cleanup than merely calling
.Xr free 3
on it, instances of the type need to begin with a magic number or string
that cannot occur at the beginning of a name.
